{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"https://pymt.readthedocs.io\"><img style=\"float: left\" src=\"../media/powered-by-logo-header.png\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Sedflux3D\n",
    "* Link to this notebook: https://github.com/csdms/pymt/blob/master/notebooks/sedflux3d.ipynb\n",
    "* Install command: `$ conda install notebook pymt_sedflux`\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Import the `Sedflux3D` component from `pymt`. All of the components available to `pymt` are located in `pymt.components`. Here I've renamed the component to be `Model` to show that you could run these same commands with other models as well. For instance, you could instead import `Child` with `from pymt.components import Child as Model` and repeat this exercise with Child instead."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Some magic to make plots appear within the notebook\n",
    "%matplotlib inline\n",
    "\n",
    "import numpy as np # In case we need to use numpy\n",
    "from tqdm import tqdm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pymt.models"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Instantiate the model. If you wanted, you could have multiple instances of the same model - each with their own state. A PyMT component is instantiate without any arguments."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = pymt.models.Sedflux3D()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "PyMT adds a docstring to the model. It is important to us that credit it given where credit is due. We want to make it clear that when we include a component in our framework the component is not ours but belong to the model's author. To that end, the model documentation includes a list of model authors, DOIs, as well as full citations to use if someone uses the model. In addition, to keep models from being black boxes, and because they are all open source, we provide links to source code. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# help(model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "rm -rf _model # Clean up for the next step"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following code is generic for all `pymt` components - not just `Sedflux3D`. First we instantiate the component and then call its `setup` method to create a model simulation with the necessary input files (note that this is ***not*** a BMI method but something added by PyMT). `setup` takes an optional argument that gives a path to a folder that will contain the necessary input files (if not provided, a temporary folder will be used). `setup` returns the name of the config file and the path to the folder containing it (we'll use this information later when we run `initialize`)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "config_file, initdir = model.setup('_model', run_duration=3650000.)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we look inside the `_model` folder, we can see all of the necessary sedflux input files ready to run."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ls _model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `initialize` method reads all of the input files and gets the model ready to update through time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.initialize(config_file, dir=initdir)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.set_value(\"channel_exit_water_flow__speed\", 1.2)\n",
    "model.set_value(\"channel_exit_x-section__mean_of_width\", 400.)\n",
    "model.set_value(\"channel_exit_x-section__mean_of_depth\", 4.)\n",
    "model.set_value(\"channel_exit_water_sediment~suspended__mass_concentration\", .01)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here we update the model for 10 time steps, printing the model time after each step."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for t in tqdm(range(10)):\n",
    "    model.update()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "From the output it appears that sedflux is operating on a 1 year time step and is using units of *days*. We can double check that assumption."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "model.time_units"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Yep, *days*. And the time step..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.time_step"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `update_until` method gives us more control by allowing us to update to a particular time. Using the `units` keyword allows us to specify the \"until\" time. Here we update the model until 20 years."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.update_until(200., units='year')\n",
    "model.time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.time_units = 'year'\n",
    "print(model.time)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We've covered how to setup and run a model, now we'll have a look at how to get data out of the model. This is done with the `get_value` method but first we need to look at what variables the model provides. This is held as a tuple of variable names and accessed through the `output_var_names` attribute."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.output_var_names"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.input_var_names"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "So to get the values of, say, water depth,"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.get_value('sea_water__depth')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As with previous methods, you can use the `units` keyword to specify units. Here we get water depths in units of parsecs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.get_value('sea_water__depth', units='parsec')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.quick_plot('sea_water__depth', vmin=-200, vmax=200, cmap='BrBG_r')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.set_value(\"channel_exit_water_sediment~suspended__mass_concentration\", .5)\n",
    "for t in tqdm(range(20)):\n",
    "    model.update()\n",
    "model.quick_plot('sea_water__depth', vmin=-200, vmax=200, cmap='BrBG_r')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
